function [hdr, bci] = readHeaderTDT( bci, varargin)
% hdr=readHeaderTDT(bci,varargin) TDT version: Reads recording system defined parameters.
%
% PURPOSE:
% Read recording system defined parameters.
% Return parameters such as  parameters for recording device, user interface, feature selection, classifier
% training, classifier evaluation.
% Which parameters are required for which experiment in documented in the
% wiki.
%
% INPUT:
% bci:      A bci structure holding a substructure TDT with field
%           dataBufferName (bci.TDT.dataBufferName)
%
% OUTPUT:
% hdr:      A hdr structure holding recording system specific data
% bci:      A bci structure holding the handles to the COM object for hardware
%           access, and for for the recording system specific data
%
%
% REQUIREMENTS:
% none
%

% CR wrote it
% JR 10/11/21 rewrote for TDT

%global read_header_var % Ugly, used to pass parameters betweeen functions
if ~isfield(bci.TDT,'DA') || ~isa(bci.TDT.DA,'COM.TDevAcc_X') % do this only if we don't have a com object for hardware access yet
    %if ~isstruct(read_header_var)% We do this only the first time the function is called
    % Access to TDT hardware
    bci.TDT.DA  = actxcontrol('TDevAcc.X');
    if bci.TDT.DA==0
        error('Could not establish TDevAcc.X control. Is the TDT system recording/previewing?')
    end
    e=bci.TDT.DA.ConnectServer('Local');
    if e==0
        error('Could not connect to TDevAcc.X server.')
    end
    disp('TDT: Connected to hardware server')
end
if ~isfield(bci.TDT,'TT') || ~isa(bci.TDT.TT,'COM.TTank_X') % do this only if we don't have a com object for data tank server access yet
    % Access to TTank server
    bci.TDT.TT=actxcontrol('TTank.X');
    if bci.TDT.TT==0
        error('Could not establish TTank.X control. Is the TDT system recording/previewing?')
    end
    e=bci.TDT.TT.ConnectServer('Local','Me');
    if e==0
        error('Could not connect to TTank.X server.')
    end
    e=bci.TDT.TT.OpenTank(bci.TDT.DA.GetTankName,'R');
    if e==0
        error('Could not open data tank.')
    end
    e=bci.TDT.TT.SelectBlock(bci.TDT.TT.GetHotBlock);
    if e==0
        error('Could not select current block.')
    end
    bci.TDT.currentBlock=bci.TDT.TT.GetHotBlock;
    disp('TDT: Connected to database server')
end

try %here we gather information
    bci.TDT.currentTank=bci.TDT.DA.GetTankName;
    bci.TDT.currentBlockNotes=bci.TDT.TT.CurBlockNotes;
    bci.TDT.params=parseBlockInfo(bci.TDT);
    if ~isfield(bci.TDT,'acqPos')
        bci.TDT.acqPos(1:size(bci.TDT.params.tagName,1))=0; % Initialize the variable
        bci.TDT.overflow(1:size(bci.TDT.params.tagName,1))=0;
    end %Here we have tag names, number of channels number of channels and sampling frequency for each block
    %Now we want, buffer sizes and acquisition positions
    %Therefore we need the d- and s-projects. These are basically
    %the lower case names of the blocks with a d or s prependend. For
    %code to find all available d- and s-projects see Open Developer man page 109
    %bci.TDT.params
    for k=1:size(bci.TDT.params.tagName,1) % for each tag name
        bci.TDT.params.dTagName{k}=['d' lower(bci.TDT.params.tagName(k,:))];
        bci.TDT.params.sTagName{k}=['s' lower(bci.TDT.params.tagName(k,:))];
        bci.TDT.params.bufferSize(k)=bci.TDT.DA.GetTargetSize([bci.TDT.dataBufferName '.' bci.TDT.params.dTagName{k}]);
        %MIGHT REQUIRE FIX. Adding the buffer size appears inconsistent
        %to me. Also fix overflow calculation three lines below then
        bci.TDT.prevPos(k)=bci.TDT.acqPos(k);
        bci.TDT.acqPos(k)=bci.TDT.DA.GetTargetVal([bci.TDT.dataBufferName '.' bci.TDT.params.sTagName{k}])+bci.TDT.params.bufferSize(k)*bci.TDT.overflow(k);
%         if bci.TDT.acqPos(k)==0 && k>1
%             error(['Cannot read from: ' [bci.TDT.dataBufferName '.' bci.TDT.params.sTagName{k}] ' Check name of amplifier in Openworkbench.'])
%         end
        if bci.TDT.prevPos(k)> bci.TDT.acqPos(k)
            bci.TDT.overflow(k)=bci.TDT.overflow(k)+1;
            bci.TDT.acqPos(k)=bci.TDT.acqPos(k)+bci.TDT.params.bufferSize(k); % correct current position in linear buffer 
        end
        bci.TDT.nSamples(k)=(bci.TDT.acqPos(k))/bci.TDT.params.nChannels(k);
        bci.TDT.nTrials(k)=1;
        %debugging
        %disp(['ov: '  num2str(bci.TDT.overflow(k)) ' nSamp: ' num2str(bci.TDT.nSamples(k))  ' prevPos: ' num2str(bci.TDT.prevPos(k)) ' curPos: ' num2str(bci.TDT.acqPos(k)) ' bufSize:' num2str(bci.TDT.params.bufferSize(k))]);
    end
    bci.TDT.Fs=bci.TDT.params.sampFreq;
    bci.TDT.nChans=bci.TDT.params.nChannels;
    hdr=bci.TDT;

catch
    rethrow(lasterror);
    % bci.TDT.DA.CloseConnection
    % bci.TDT.TT.ReleaseServer
end

%WHERE DO WE CLEAN UP ?????

% Clean up
% close the servers
% bci.TDT.DA.CloseConnection
% bci.TDT.TT.ReleaseServer

%% This is code from the ecog analysis box

function params=parseBlockInfo(TDT)
%orignal function is ecogTDTGetBlockInfo
% pass a
try
    % Thats contains everything but is ugly
    params.notes=TDT.currentBlockNotes;
    %Thats the same for all tags
    params.totalTime = TDT.TT.CurBlockStopTime- TDT.TT.CurBlockStartTime; %Gets total tank duration.

    %Get the tag codes
    eventCodes=TDT.TT.GetEventCodes(0);
    %translate them
    tagNames=[];
    sampFreq=[];
    nChannels=[];
    dataFormat=[];
    idxHDRStart=findstr(params.notes,'[');
    idxHDRStart=[idxHDRStart length(params.notes)];

    for k=1:length(eventCodes)
        tagNames=strvcat(tagNames, TDT.TT.CodeToString(eventCodes(k)));
        % try to get the number of channels associated with that field
        idx1=strfind(params.notes,['VALUE=' tagNames(k,:)]);
        % We may have found multiple occurences and scan them now
        m=1;
        while m<=length(idx1)
            tmpIdx=max(find(idxHDRStart<idx1(m))); % where the current header block starts
            %Get the header block
            tmpString=params.notes(idxHDRStart(tmpIdx):idxHDRStart(tmpIdx+1));
            % Now the line containing the number of channels in this block
            idxLineStart=strfind(tmpString,'NAME=NumChan;TYPE=');
            lineLength=min(find(double(tmpString(idxLineStart(1):end))==13));
            tmpString=tmpString(idxLineStart(1):idxLineStart(1)+lineLength);
            % the number of channels. The line ends with a semikolon which
            % we skip
            tmp=str2num(tmpString(findstr(tmpString,'VALUE=')+length('VALUE='):end-1));
            if ~isempty(tmp)
                nChannels=[nChannels;tmp];
                m=length(idx1)+1; % and we stop when we found something
            elseif isempty(tmp) && m==length(idx1) % no channel number spcified for this tag
                nChannels=[nChannels;0];
                m=m+1; % We stop here
            else
                m=m+1; % try the next block
            end

        end
        %load the infor associated with the data tag
        res=TDT.TT.GetCodeSpecs(TDT.TT.StringToEvCode(tagNames(k,:)));
        %Get the frequency
        sampFreq=[sampFreq;TDT.TT.EvSampFreq(1)];

        %TDT.TT.EvDataSize(1)
    end
    params.tagName=tagNames;
    params.sampFreq=sampFreq;
    params.nChannels=nChannels;
    %invoke(TDT.TT,'CloseTank')%closes the server.

catch %Make sure the server is closed if anything chrashes
    rethrow(lasterror);
    %invoke(TDT.TT,'CloseTank')%closes the server.
end
return
